package com.itcam.service;

import com.itcam.dao.StudentDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.io.FileInputStream;
import java.io.FileNotFoundException;

/**
 * Author:Cammy.Wu
 * Date:2024-04-26
 * Description:
 */

@Service
//@Transactional(timeout = 3)
public class StudentService {

    @Autowired
    private StudentDao studentDao;

    /**
     * 添加事务：
     *
     * @Transactional 位置： 方法上|类上
     * 方法： 当前方法有事务
     * 类：   类下的所有方法都有事务
     * <p>
     * 1.只读模式
     * 只读模式可以提升查询事务的效率！推荐事务中只有查询代码，使用只读模式！
     * 默认：boolean readOnly() default false;
     * 解释：一般情况下，都是通过类添加事务注解的，这个时候类下所有方法都有事务，将查询的方法设置为只读模式
     * <p>
     * 2.超时时间
     * 默认：永远不超时 -1
     * 位置 timeout = 时间 秒数 超时时间，就会回滚事务和释放异常
     *
     * 3.指令异常回滚和指令异常不回滚：
     *      默认情况下，指定发生运行时异常事务才会回滚！
     *      我们可以指定Exception异常来控制所有异常都回滚！
     *      rollbackFor = Exception.class
     *      noRollbackFor = 回滚异常范围内，控制某个异常不回滚
     *
     * 4.隔离级别设置
     *      推荐设置第二个隔离级别！
     *      isolation = Isolation.READ_UNCOMMITTED
     *      isolation = Isolation.READ_COMMITTED
     *      isolation = Isolation.REPEATABLE_READ
     *      isolation = Isolation.SERIALIZABLE
     *      1.  读未提交（Read Uncommitted）：事务可以读取未被提交的数据，容易产生脏读、不可重复读和幻读等问题。实现简单但不太安全，一般不用。
     *      2.  读已提交（Read Committed）：事务只能读取已经提交的数据，可以避免脏读问题，但可能引发不可重复读和幻读。
     *      3.  可重复读（Repeatable Read）：在一个事务中，相同的查询将返回相同的结果集，不管其他事务对数据做了什么修改。可以避免脏读和不可重复读，但仍有幻读的问题。
     *      4.  串行化（Serializable）：最高的隔离级别，完全禁止了并发，只允许一个事务执行完毕之后才能执行另一个事务。可以避免以上所有问题，但效率较低，不适用于高并发场景。
     */

    @Transactional(readOnly = false,rollbackFor = Exception.class,noRollbackFor = FileNotFoundException.class,
            isolation = Isolation.READ_UNCOMMITTED)
    public void changeInfo() throws FileNotFoundException {
        studentDao.updateAgeById(77, 1);

//        int i = 1 / 0;

//        try {
//            Thread.sleep(4000);
//        } catch (InterruptedException e) {
//            throw new RuntimeException(e);
//        }

        FileInputStream xxxx = new FileInputStream("xxxx");
        System.out.println("-----------");
        studentDao.updateNameById("test1", 1);
    }

    @Transactional(readOnly = true)
    public void getStudentInfo() {
        //获取学生信息 查询数据库 不修改
    }

    /**
     * 声明两个独立修改数据库的事务业务方法
     * 设置传播行为
     *
     * propagation:
     *      propagation = Propagation.(推荐使用默认值)
     *      REQUIRED(默认值):如果父方法有事务，就加入，如果没有就新建自己独立！
     *      REQUIRES_NEW:不管父方法是否有事务，我都新建事务，都是独立的！
     */
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void changeAge(){
        studentDao.updateAgeById(17,1);
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void changeName(){
        studentDao.updateNameById("姬如雪",1);
        int i = 1/0;
    }
}
